﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Steering.SteeringAbstraction;
using System.Diagnostics;

namespace SteeringWheelAdapter
{
    public class WheelSteering : ForkliftSteeringSource
    {
        public override event EventHandler StopIssued = null;
        public override event EventHandler MenuIssued = null;

        [StructLayout(LayoutKind.Sequential, Size = 20)]
        private unsafe struct SteeringWheel
        {
            public int stick;
            public int axis;
            public float pos;
            public int button;
            public int type;
        }
        
        [DllImport("AllegroJoystict.dll", CallingConvention = CallingConvention.Cdecl)]
        private unsafe static extern void Update(ref SteeringWheel joyStruct);

        private SteeringWheel wheel;

        public WheelSteering()
        {
            wheel = new SteeringWheel();
        }

        private enum SteeringModule
        {
            Wheel = 0,
            Pedal = 1
        }

        private enum SteeringType
        {
            Turning = 1,
            Push = 2,
            Release = 3
        }

        private enum SteeringForkButton
        {
            Up = 2,
            Middle = 4,
            Down = 6,
            Exit = 8,
            Stop = 10
        }

        public unsafe override void UpdateSteering()
        {
            Update(ref wheel);
            ProcessWheelValues();
        }

        private void ProcessWheelValues()
        {
            SteeringModule module = (SteeringModule)wheel.axis;
            switch (module)
            {
                case SteeringModule.Pedal:
                    {
                        this.speed.Value = wheel.pos;
                    }
                    break;
                case SteeringModule.Wheel:
                    {
                        SteeringType type = (SteeringType)wheel.type;
                        switch (type)
                        {
                            case SteeringType.Turning:
                                {
                                    this.turn.Value = wheel.pos;
                                }
                                break;
                            case SteeringType.Push:
                                {
                                    SteeringForkButton button = (SteeringForkButton)wheel.button;
                                    switch (button)
                                    {
                                        case SteeringForkButton.Up:
                                            {
                                                this.forkSpeed.Value = 1.0;
                                            }
                                            break;
                                        case SteeringForkButton.Middle:
                                            {
                                                this.forkSpeed.Value = 0.0;
                                            }
                                            break;
                                        case SteeringForkButton.Down:
                                            {
                                                this.forkSpeed.Value = -1.0;
                                            }
                                            break;
                                        case SteeringForkButton.Exit:
                                            {
                                                MenuIssued(this, null);
                                            }
                                            break;
                                        case SteeringForkButton.Stop:
                                            {
                                                StopIssued(this, null);
                                            }
                                            break;
                                        default:
                                            //throw new Exception("unsupported button pressed");
                                            break;
                                    }
                                }
                                break;
                            case SteeringType.Release:
                                {
                                    // do nothing for now
                                }
                                break;
                            default:
                                //throw new Exception("unsupported steering type");
                                break;
                        }
                    }
                    break;
                default:
                    //throw new Exception("Unsupported type of steering module");
                    break;
            }
        }


        public override bool StartSteering()
        {
            // TODO: use this somehow?
            return true;
        }

        public override void StopSteering()
        {
            MenuIssued(this, null);
        }
    }
}
